#include <stdbool.h>
#include "MQTTClient.h"
#include "mqtt_connect.h"
#include "i_device_id.h"

#define MQTT_BROKER                "broker.emqx.io"    // 改成你的MQTT Broker 地址
// #define MQTT_BROKER                "47.82.107.28"       // 改成你的 MQTT Broker 地址
#define MQTT_PORT                  1883                 // 端口号
int g_mqtt_flag = 0;
extern bool g_wifi_connect_flag;

MQTTMessage ackmsg;
MQTTClient client;
int needAck = 0;
mqtt_msg mq_msg;

#define MQTT_TOPIC "warehouse/alarm"
char topic_buffer[16] = MQTT_TOPIC;

struct opts_struct {
    char *clientid;     // 客户ID
    int nodelimiter;    // 有无分隔符标志
    char *delimiter;    // 分隔符
    enum QoS qos;       // 服务质量
    char *username;     // 用户名
    char *password;     // 密码
    char *host;         // 服务器地址
    int port;           // 端口号
    int showtopics;     // 打印订阅的主题
};

/**
 * @brief   这是默clientid, 实际使用会改成唯一ID
 *
 */
char g_clientid[32] = "itinymltest0";

/**
 * @brief   客户ID是唯一的，不可重复，重复会把前面连接的挤下线
 *
 */
struct opts_struct opts = {.clientid = g_clientid,
                           .nodelimiter = 0,
                           .delimiter = (char *)"\n",
                           .qos = QOS0,
                           .username = "admin",
                           .password = "public",
                           .host = (char *)MQTT_BROKER,
                           .port = MQTT_PORT,
                           .showtopics = 1};

char mq_buf[100];

/**
 * @brief 读取MQTT接收到的数据
 * @param buf 存放数据的指针
 * @retval void
 */
void read_mqtt_data(char *buf)
{
    strcpy(buf, (const char *)mq_buf); // 复制MQTT的数据
    memset(mq_buf, 0, 100);
}

/* 发送数据 */
void i_mqtt_send(char *info)
{
    printf("%s\n", info);
    MQTTMessage message;
    const char* payload = info;
    message.qos = QOS0;
    message.retained = 0;
    message.dup = 0;
    message.payload = (void*)payload;
    message.payloadlen = strlen(payload);
    if (g_mqtt_flag) {
        MQTTPublish(&client, MQTT_TOPIC, &message);
    }
}

/**
  * @brief 发送MQTT消息
  * @param msg 要发送的消息
  * @retval void
 */
void MQTT_SendData(mqtt_msg *msg)
{
    ackmsg.payload = msg->send_data;
    MQTTPublish(&client, msg->publish, &ackmsg);
}

/**
  * @brief 消息接收处理
  * @param md 消息数据
  * @retval void
 */
void messageArrived(MessageData* data)
{
    // MQTTMessage *message = md->message;
    // printf("%.*s\n", (int)message->payloadlen, (char *)message->payload);
    // strcpy(mq_buf, (const char *)message->payload);         // 复制接收到的数据
    // printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
    //        data->message->payloadlen, data->message->payload);
    (void)data->topicName->lenstring.len;
    (void)data->topicName->lenstring.data;
    (void)data->message->payloadlen;
    (void)data->message->payload;
}

unsigned char sendbuf[512];
unsigned char readbuf[512];

/**
  * @brief 连接到MQTT服务
  * @param msg MQTT消息结构体
  * @retval void
 */
int MQTT_Connect(mqtt_msg *msg)
{
    int rc = 0;
    int i = 0;

    MQTTMessage pubmsg;

    i_get_device_id(g_clientid);

    printf("topic is %s\n", msg->subscriber);
    printf("clientid is %s\n", g_clientid);

    Network mqtt_net;

    // MQTTClient client;
    NetworkInit(&mqtt_net);                                 // 网络初始化
    rc = NetworkConnect(&mqtt_net, opts.host, opts.port);   // 网络连接
    if (rc != SUCCESS) {        // 失败
        printf("NetworkConnect fail: %d\n", rc);
        while (1) {
            sleep(1);
        }
    }
    printf("NetworkConnect success\n");

    if ((rc = MQTTStartTask(&client)) != SUCCESS) {
        printf("Return code from start tasks is %d\n", rc);
    }

    MQTTClientInit(&client, &mqtt_net, 1000, sendbuf, sizeof(sendbuf), readbuf, sizeof(readbuf));   // 设置MQTT缓存

    // if ((rc = MQTTStartTask(&client)) != SUCCESS) {
    //     printf("Return code from start tasks is %d\n", rc);
    // }

    /* 设置MQTT相关参数 */
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = opts.clientid;
    data.username.cstring = opts.username;
    data.password.cstring = opts.password;

    data.keepAliveInterval = 10;
    data.cleansession = 1;
    printf("Connecting to %s %d\n", opts.host, opts.port);

    while(1)  {
        rc = MQTTConnect(&client, &data);                               // 连接到MQTT服务器
        if (rc != SUCCESS) {
            printf("MQTTConnect fail:%d\n", rc);
            sleep(1);
        } else {
            printf("MQTTConnect success\n");
            break;
        }
    }

    rc = MQTTSubscribe(&client, msg->subscriber, opts.qos, messageArrived);   // 订阅主题和接收消息
    if (rc != SUCCESS) {
        printf("MQTTSubscribe fail:%d\n", rc);
        while (1) {
            sleep(1);
        }
    }
    printf("MQTTSubscribe %s success\n", msg->subscriber);

    /** 设置消息参数 **/
    memset(&ackmsg, '\0', sizeof(ackmsg));
    ackmsg.payload = (void *)"{data:1}";
    ackmsg.payloadlen = strlen((char *)ackmsg.payload);
    ackmsg.qos = QOS0;
    ackmsg.retained = 0;
    ackmsg.dup = 0;
    g_mqtt_flag = true;

#if 1
    while (1) {
        sleep(2);
    }
    printf("Stopping\n");
    MQTTDisconnect(&client);            // 断开MQTT的连接
    MqttNetworkDisconnect(&mqtt_net);   // 关闭网络连接
#endif
    return 0;
}

/**
  * @brief MQTT任务
  * @param void
  * @retval void
 */
static void MQTTTask(void *arg)
{
    (void)arg;

    while (g_wifi_connect_flag == false) {
        sleep(1);
    }
    sleep(2);
    mq_msg.subscriber = topic_buffer; // 订阅的主题赋值
    MQTT_Connect(&mq_msg); // 连接到MQTT服务器
}

/**
  * @brief MQTT任务创建
  * @param void
  * @retval void
 */
static void MQTTTaskEntry(void)
{
    /** 任务属性的结构体 **/
    osThreadAttr_t attr;

    attr.name = "MQTTTask";         //任务名称
    attr.attr_bits = 0U;            //任务的属性位
    attr.cb_mem = NULL;             //任务控制块的内存初始地址，默认为系统自动分配
    attr.cb_size = 0U;              //任务控制块的内存大小
    attr.stack_mem = NULL;          //任务的内存初始地址，默认为系统自动分配
    attr.stack_size = 8192;         //任务的内存大小
    attr.priority = 30;             //任务的优先级

    /** 创建任务 **/
    if (osThreadNew((osThreadFunc_t)MQTTTask, NULL, &attr) == NULL) {
        printf("[PWMTaskEntry] Falied to create MQTTTask!\n");
    }
}

/** 让系统运行指定的函数 **/
SYS_RUN(MQTTTaskEntry);